package com.bitin.common.data.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 实体通用父类
 *
 * @Author: Mr.Lu
 * @Datetime 2024/8/13 22:34
 */
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditModel implements Serializable {

    /**
     * 主键
     *
     * AUTO:     默认值,主键由程序控制
     * IDENTITY: 数据库自动增长, Oracle不支持这种方式 ORACLE 靠序列来提供类似自增长的功能
     * SEQUENCE: 通过数据库的序列产生主键, MYSQL不支持 MYSQL没有序列的概念
     * Table:    提供特定的数据库产生主键
     */
    @Id
    @GenericGenerator(name = "snowflakeIdGenerator", strategy = "com.bitin.common.data.config.SnowflakeIdGenerator")
    @GeneratedValue(generator = "snowflakeIdGenerator")
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    @Column(name = "id", nullable = false, length = 64)
    private String id;

    @CreatedBy
    @Column(name = "created_user_id", nullable = false, updatable = false, length = 64)
    // @CreatedBy 这个可能会被 AuditingEntityListener 覆盖，为了⽅便测试，我们先注释掉
    protected String createdUserId;
    /**
     * 创建时间
     */
    //@Temporal(TemporalType.TIMESTAMP)
    @CreatedDate
    @Column(name = "created_time", nullable = false, updatable = false)
    private LocalDateTime createdTime;

    @LastModifiedBy
    @Column(name = "last_modified_user_id", nullable = false, length = 64)
    protected String lastModifiedUserId;
    /**
     * 上次更新时间
     */
    //@Temporal(TemporalType.TIMESTAMP)
    @LastModifiedDate
    @Column(name = "last_modified_time", nullable = false)
    private LocalDateTime lastModifiedTime;

    /**
     * 由于本身有乐观锁机制，这个我们测试的时候先注释掉，改⽤⼿动设置的值；
     */
    @Version
    protected Long version;

    @Column(name = "deleted", nullable = false)
    protected boolean deleted;
    /**
     * 删除原因
     */
    @Column(name = "deleted_reason")
    protected String deletedReason;

    @PreUpdate
    public void preUpdate() {
        System.out.println("preUpdate::" + this);
        this.setCreatedUserId("200");
    }

    @PostUpdate
    public void postUpdate() {
        System.out.println("postUpdate::" + this);
    }

    @PreRemove
    public void preRemove() {
        System.out.println("preRemove::" + this);
    }

    @PostRemove
    public void postRemove() {
        System.out.println("postRemove::" + this);
    }

    @PostLoad
    public void postLoad() {
        System.out.println("postLoad::" + this);
    }
}
